﻿//--------------------------------------
// Copyright     : W.A.I.S. TECHNOLOGY 2003-2008 ; http://www.wais-fr.com ; email: infos@wais-fr.com
// Author        : Henri d'Orgeval
// Contributors  : 
// Last release  : 2007/11/15 (yy/mm/dd)
// Version       : 1.0.0.5
// Pattern       : "Real Time Trace"
// Internal name : TraceLogFileProvider (RealTimeTrace Log File Data Adapater)
// Description   : this class is a wrapper to manage the Real Time Trace to a flat text file.
//                 
// Framework     : v2.0.50727 and above
//
// Licence       : Microsoft Permisse Licence
// W.A.I.S provides this code in the hope that it will be useful, but WITHOUT ANY WARRANTY , either express or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose.          
// This library is free software; you can redistribute it and/or modify it under the terms of the Microsoft Permissive Licence
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//---------------------------------------

using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;

namespace RealtimeTrace
{
    sealed internal class TraceLogFileProvider 
        : Itraceable, ITraceDataProvider
    {

        #region Itraceable Members

        /// <summary>
        /// Use this method to initialize the RealTimeTrace.
        /// This method should be called within the class constructor(s) 
        /// if you want to override the default RealtimeTrace configuration.
        /// </summary>
        private void InitializeRealTimeTrace()
        {
            this.RealTimeTraceProvider = DataProviderType.None;
            this.PreferredDumpType = DumpType.XML;
            this.ErrorsMaxSize = 4096;
        }

        /// <summary>
        /// By default, all exceptions that are raised within the RealtimeTrace layer
        /// are not saved by the Data Storage provider.
        /// </summary>
        private DataProviderType _RealTimeTraceProvider = DataProviderType.None;
        /// <summary>
        /// Gets or Sets the Data Store provider for the RealTimeTrace.
        /// By default this property returns 'LogFile'
        /// </summary>
        public DataProviderType RealTimeTraceProvider
        {
            get
            {
                return this._RealTimeTraceProvider;
            }
            set
            {
                this._RealTimeTraceProvider = value;
            }
        }

        private DumpType _PreferredDumpType = DumpType.XML;
        public DumpType PreferredDumpType
        {
            get
            {
                return this._PreferredDumpType;
            }
            set
            {
                this._PreferredDumpType = value;
            }
        }

        /// <summary>
        /// Sets any internal error message that occured within the execution of the RealTimeTrace Layer.
        /// The error message can be read by the implementor through the LastError property.
        /// </summary>
        /// <returns></returns>
        private string InternalError
        {
            set
            {
                try
                {
                    if (System.String.IsNullOrEmpty(value))
                    {
                        return;
                    }
                    this._LastError = value;
                    this._Errors = value;
                    this._HasErrors = true;
                }
                catch (Exception)
                {
                    // this code should never run, but who knows ...
                }
            }
        }

        private bool _HasErrors = false;
        public bool HasErrors
        {
            get { return this._HasErrors; }
            set { this._HasErrors = value; }
        }

        private System.String _LastError = System.String.Empty;
        public string LastError
        {
            get { return this._LastError; }
            set
            {
                if (value == null)
                {
                    value = System.String.Empty;
                }
                this._LastError = value;
            }
        }

        private System.String _Errors = System.String.Empty;
        public string Errors
        {
            get { return this._Errors; }
            set
            {
                if (value == null)
                {
                    value = System.String.Empty;
                }
                this._Errors = value;
            }
        }

        /// <summary>
        /// Clear any previous error messages hold by the property 'LastError'.
        /// The 'HasErrors' property is reset to false.
        /// Call this method at the beginning of all public methods in your class.
        /// </summary>
        private void ClearErrors()
        {
            try
            {
                this._Errors = System.String.Empty;
                this._LastError = System.String.Empty;
                this._HasErrors = false;
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// Add an error message to the current content of the 'Errors' Property.
        /// The 'HasErrors' property is set to true.
        /// </summary>
        /// <param name="errorMessage">Any message to be added to the Errors Property</param>
        /// <returns></returns>
        /// <remarks>Be carefull: by calling this method many times without calling the 'ClearErrors' in between,
        /// you might create a memory leak in your application.</remarks>
        private bool AddError(string errorMessage)
        {
            try
            {
                if (System.String.IsNullOrEmpty(errorMessage))
                {
                    return true;
                }

                this._HasErrors = true;

                // Update the LastError message
                this._LastError = errorMessage;

                // Update the Errors message
                this._Errors += errorMessage;
                this._Errors += "\r\n";

                // check for the constraint on this._Errors string length.
                // the purpose of this check is to avoid a possible memory leak.
                if (this._Errors.Length > this._ErrorsMaxSize)
                {
                    this._Errors = errorMessage;
                }

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// Set the default maximum length of the Errors property to 4096 bytes.
        /// This threshold should prevent memory leak due to exceptions storms.
        /// </summary>
        private int _ErrorsMaxSize = 4096;
        /// <summary>
        /// Gets or Sets the maximum length in bytes for the 'Errors' property.
        /// Default value is 4096 bytes.
        /// </summary>
        private int ErrorsMaxSize
        {
            get
            {
                return this._ErrorsMaxSize;
            }
            set
            {

                if (value > 0)
                {
                    this._ErrorsMaxSize = value;
                }
            }
        }

        /// <summary>
        /// Log into the trace data store the error message.
        /// </summary>
        /// <param name="errorMessage">Any error message to be logged.</param>
        private void RealTimeTrace(string errorMessage)
        {
            try
            {
                if (System.String.IsNullOrEmpty(errorMessage))
                {
                    return;
                }

                if (!this.AddError(errorMessage))
                {
                    // something goes wrong ...     
                }
            }
            catch (Exception ex)
            {

                // this code should never run, but who knows ...
                this.InternalError = ex.Message;
            }

        }

        /// <summary>
        /// Log into the trace data store the current exception.
        /// </summary>
        /// <param name="ex">The current exception object to be analyzed and logged for further analysis.</param>
        private void RealTimeTrace(Exception ex)
        {
            try
            {
                if (ex == null)
                {
                    return;
                }

                if (!this.AddError(ex.Message))
                {
                    // something goes wrong ...     
                }
            }
            catch (Exception ex1)
            {
                // this code should never run, but who knows ...
                this.InternalError = ex1.Message;
            }
        }

        /// <summary>
        /// Log into the trace data store the current exception.
        /// </summary>
        /// <param name="ex">The current exception object to be analyzed and logged.</param>
        /// <param name="args">Any number of objects that represent the calling parameters of the method in which an exception has been thrown.</param>
        private void RealTimeTrace(Exception ex, params object[] args)
        {
            try
            {
                if (ex == null)
                {
                    return;
                }

                if (!this.AddError(ex.Message))
                {
                    // something goes wrong ...     
                }
            }
            catch (Exception ex1)
            {
                // this code should never run, but who knows ...
                this.InternalError = ex1.Message;
            }
        }


        #endregion

        #region Formatting methods
        private const string LINE_SEPARATOR = "--------------------------------------------------------------------------------";
        
        private string _FormattedMessage = System.String.Empty;
        /// <summary>
        /// Gets or Sets the formatted message to be stored
        /// </summary>
        private string FormattedMessage
        {
            get
            {
                return this._FormattedMessage;
            }
            set
            {
                if (value == null)
                {
                    this._FormattedMessage = System.String.Empty;
                    return;
                }

                this._FormattedMessage = value;
            }
        }

        /// <summary>
        /// Generates a formatted string to display the content of the traceInfo object.
        /// </summary>
        /// <param name="traceInfo">the ItraceInfo object that holds 
        /// complete infos about the exception and its context.</param>
        /// <returns>Returns true if formatting has succeeded, false otherwise.</returns>
        private bool FormatMessage(ITraceInfo traceInfo)
        {
            try
            {
                // Initialize the Formatted string
                this.FormattedMessage = System.String.Empty;

                // Check input parameters
                if (traceInfo == null)
                {
                    return true;
                }

                System.Text.StringBuilder myBuilder = new StringBuilder();
                string myLine ;
                string myIndent = "\t";

                myLine = LINE_SEPARATOR;
                myBuilder.AppendLine(myLine);

                // Generic information about the exception : Where/when/what
                myLine = System.String.Format("Date...........: {0}", traceInfo.Date.ToString());
                myBuilder.AppendLine(myLine);

                myLine = System.String.Format("Rank...........: {0}", traceInfo.Count.ToString());
                myBuilder.AppendLine(myLine);

                myLine = System.String.Format("Message........: {0}", traceInfo.Message);
                myBuilder.AppendLine(myLine);

                myLine = System.String.Format("Class..........: {0}", traceInfo.ClassName);
                myBuilder.AppendLine(myLine);

                myLine = System.String.Format("Method.........: {0}", traceInfo.MethodName);
                myBuilder.AppendLine(myLine);

                myLine = System.String.Format("Thread.........: {0}", traceInfo.ThreadID);
                myBuilder.AppendLine(myLine);

                myLine = System.String.Format("Culture........: {0}", traceInfo.Culture);
                myBuilder.AppendLine(myLine);

                myLine = System.String.Format("UICulture......: {0}", traceInfo.UICulture);
                myBuilder.AppendLine(myLine);

                myLine = System.String.Format("Exception type : {0}", traceInfo.ExceptionType);
                myBuilder.AppendLine(myLine);

                // Description of the parameters and there respective values
                myLine = System.String.Format("{0}{1}", myIndent, LINE_SEPARATOR);
                myBuilder.AppendLine(myLine);

                myLine = System.String.Format("{0}{1}", myIndent, "Parameter(s) details at runtime :");
                myBuilder.AppendLine(myLine);

                myLine = System.String.Format("{0}{1}", myIndent, LINE_SEPARATOR);
                myBuilder.AppendLine(myLine);
                if (!FormatMessage(traceInfo.ParamInfoCollection,myBuilder))
                {
                    // TODO : think of it for the next release
                }
                myLine = System.String.Format("{0}{1}", myIndent, LINE_SEPARATOR);
                myBuilder.AppendLine(myLine);

                // Description of the additional parameters and there respective values
                myLine = System.String.Format("{0}{1}", myIndent, LINE_SEPARATOR);
                myBuilder.AppendLine(myLine);

                myLine = System.String.Format("{0}{1}", myIndent, "Additional parameter(s) details at runtime :");
                myBuilder.AppendLine(myLine);

                myLine = System.String.Format("{0}{1}", myIndent, LINE_SEPARATOR);
                myBuilder.AppendLine(myLine);
                if (!FormatMessage(traceInfo.ExtendedParamInfoCollection, myBuilder))
                {
                    // TODO : think of it for the next release
                }
                myLine = System.String.Format("{0}{1}", myIndent, LINE_SEPARATOR);
                myBuilder.AppendLine(myLine);

                // Exception Stack
                myLine = System.String.Format("Exception Stack :");
                myBuilder.AppendLine(myLine);
                myLine = System.String.Format("{0}{1}", myIndent, LINE_SEPARATOR);
                myBuilder.AppendLine(myLine);
                myLine = System.String.Format("{0}", traceInfo.ExceptionStack);
                myBuilder.AppendLine(myLine);
                myLine = System.String.Format("{0}{1}", myIndent, LINE_SEPARATOR);
                myBuilder.AppendLine(myLine);

                // Environment Stack
                myLine = System.String.Format("Environment Stack :");
                myBuilder.AppendLine(myLine);
                myLine = System.String.Format("{0}{1}", myIndent, LINE_SEPARATOR);
                myBuilder.AppendLine(myLine);
                myLine = System.String.Format("{0}", traceInfo.EnvironmentStack);
                myBuilder.AppendLine(myLine);
                myLine = System.String.Format("{0}{1}", myIndent, LINE_SEPARATOR);
                myBuilder.AppendLine(myLine);

                // Instance Class dump
                myLine = System.String.Format("Instance Class Dump :");
                myBuilder.AppendLine(myLine);
                myLine = System.String.Format("{0}{1}", myIndent, LINE_SEPARATOR);
                myBuilder.AppendLine(myLine);
                myLine = System.String.Format("{0}{1}",myIndent, traceInfo.ClassDump);
                myBuilder.AppendLine(myLine);
                myLine = System.String.Format("{0}{1}", myIndent, LINE_SEPARATOR);
                myBuilder.AppendLine(myLine);


                this.FormattedMessage = myBuilder.ToString();
                return true;
            }
            catch (Exception ex)
            {
                RealTimeTrace(ex, traceInfo);
                return false;
            }
        }

        private bool FormatMessage(System.Collections.Generic.List<ITraceParamInfo> paramInfoCollection, System.Text.StringBuilder stringBuilder)
        {
            try
            {
                // Check input parameters
                if (stringBuilder == null)
                {
                    return true;
                }

                System.Text.StringBuilder myBuilder = stringBuilder;
                string myLine;
                string myIndent = "\t";

                // Check input parameters
                if (paramInfoCollection == null)
                {
                    myLine = System.String.Format("{0}\t{1}", myIndent, "no parameters");
                    myBuilder.AppendLine(myLine);
                    return true;
                }

                // Check input parameters
                if (paramInfoCollection.Count == 0)
                {
                    myLine = System.String.Format("{0}\t{1}", myIndent, "no parameters");
                    myBuilder.AppendLine(myLine);
                    return true;
                }

                int myCounter = -1;
                foreach (ITraceParamInfo item in paramInfoCollection)
                {
                    // Check if we need to insert a dashed line between two parameters
                    myCounter += 1;
                    if (myCounter > 0)
                    {
                        myLine = System.String.Format("{0}\t---------------------", myIndent);
                        myBuilder.AppendLine(myLine);
                    }

                    if (item == null)
                    {
                        continue;
                    }
                    myLine = System.String.Format("{0}\tParam{1} Name, Type : {2}, {3} ", myIndent, item.Position + 1, item.Name, item.ParameterType);
                    myBuilder.AppendLine(myLine);

                    myLine = System.String.Format("{0}\tParam{1} Value..... : '{2}'",myIndent, item.Position + 1, item.Value);
                    myBuilder.AppendLine(myLine);

                    myLine = System.String.Format("{0}\tParam{1} Dump...... : '{2}'", myIndent, item.Position + 1, item.Dump);
                    myBuilder.AppendLine(myLine);

                    // Check for any details for this parameter
                    if (item.Details == null)
                    {
                        continue;
                    }

                    // Check for any details for this parameter
                    if (item.Details.Count == 0)
                    {
                        continue;
                    }

                    // Get any details for this parameter
                    foreach (string myKey in item.Details.Keys)
                    {
                        // check for a null reference
                        string myValue = "null";
                        if (!(item.Details[myKey] == null))
                        {
                            myValue = item.Details[myKey].ToString();
                        }

                        myLine = System.String.Format("{0}\tParam{1} {2} : '{3}'", myIndent, item.Position + 1, myKey, myValue);
                        myBuilder.AppendLine(myLine);
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                RealTimeTrace(ex, paramInfoCollection, stringBuilder);
                return false;
            }
        }
        #endregion

        #region ITraceDataProvider Members

        public bool Insert(ITraceInfo traceInfo)
        {
            try
            {
                // Clear any previous errors to avoid memory leak
                this.ClearErrors();

                // Check input parameters
                if (traceInfo == null)
                {
                    throw new System.ArgumentNullException();
                }

                if (! this.FormatMessage(traceInfo))
                {
                    throw new RealTimeTraceException("Cannot format traceInfo");
                }

                if (! this.Insert(this.FormattedMessage))
                {
                    throw new RealTimeTraceException("Cannot insert into Data Store");
                }
                
                return true;
            }
            catch (Exception ex)
            {
                RealTimeTrace(ex, traceInfo);
                return false;
            }
        }

        private bool _UseApplicationNameAsPrefix = true;
        /// <summary>
        /// Gets or Sets if the Data store name should begin with the name of the running Executable.
        /// </summary>
        public bool UseApplicationNameAsPrefix
        {
            get
            {
                return this._UseApplicationNameAsPrefix;
            }
            set
            {
                this._UseApplicationNameAsPrefix = value;
            }
        }

        #endregion

        #region DataStore Insertion methods
        private string _ExeProcessName = System.String.Empty;
        /// <summary>
        /// Gets the name of the windows process 
        /// in which the current assembly is executing.
        /// </summary>
        private string ExeProcessName
        {
            get
            {
                try
                {
                    // Check if we have already setup the internal variable
                    if (this._ExeProcessName.Length > 0)
                    {
                        return this._ExeProcessName;
                    }

                    // try to find the name of the windows process 
                    // in which the current assembly is executing.
                    System.Diagnostics.Process myProcess = System.Diagnostics.Process.GetCurrentProcess();
                    using (myProcess)
                    {
                        this._ExeProcessName = myProcess.ProcessName;
                    }  // myProcess.Dispose() is implicitely called, even in cas of an exception

                    return this._ExeProcessName;

                }
                catch (Exception ex)
                {
                    RealTimeTrace(ex);
                    return System.String.Empty;
                }
            }
        }

        private string _WebApplicationFolder = System.String.Empty;
        /// <summary>
        /// Gets the absolute path to the root Web Application folder.
        /// </summary>
        private string WebApplicationFolder
        {
            get
            {
                try
                {
                    // Check if we have already setup the internal variable
                    if (this._WebApplicationFolder.Length > 0)
                    {
                        return this._WebApplicationFolder;
                    }

                    // Extract the aspx page name from the current HttpContext
                    string myWebPagePhysicalFilePath = System.Web.HttpContext.Current.Request.PhysicalPath;
                    string myWebPagePhyicalFolderPath = System.IO.Path.GetDirectoryName(myWebPagePhysicalFilePath);

                    //this._WebApplicationFolder = System.Web.HttpRuntime.AppDomainAppPath;
                    this._WebApplicationFolder = myWebPagePhyicalFolderPath;

                    return this._WebApplicationFolder;
                }
                catch (Exception ex)
                {
                    RealTimeTrace(ex);
                    return System.String.Empty;
                }
            }
        }

        /// <summary>
        /// Checks if the current running assembly is hosted in an ASP.NET worker process.
        /// Returns True if the Host process is one of the following ASP.NET Worker process :
        /// aspnet_wp (Windows XP), w3wp (Windows 2003), webdev.webserver (VS2008 Web server)
        /// </summary>
        private bool IsWebApplication
        {
            get
            {
                try
                {
                    // Check for an ASP.NET Web application
                    if (this.ExeProcessName.ToLower().StartsWith("aspnet_wp"))
                    {
                        return true;
                    }

                    // Check for an ASP.NET Web application
                    if (this.ExeProcessName.ToLower().StartsWith("w3wp"))
                    {
                        return true;
                    }

                    // Check for an ASP.NET Web application in debug mode within Visual Studio 2008
                    if (this.ExeProcessName.ToLower().StartsWith("webdev.webserver"))
                    {
                        return true;
                    }

                    // by default, let's consider that the current running assembly is NOT a Web Application.
                    return false;
                }
                catch (Exception ex)
                {
                    RealTimeTrace(ex);
                    return false;
                }
            }
        }


        private string _WebPageName = System.String.Empty;
        /// <summary>
        /// Gets the name of the aspx page in which an Exception has been fired.
        /// </summary>
        private string WebPageName
        {
            get
            {
                try
                {
                    // Check if we have already setup the internal variable
                    if (this._WebPageName.Length > 0)
                    {
                        return this._WebPageName;
                    }

                    // Extract the aspx page name from the current HttpContext
                    string myWebPagePhysicalFilePath = System.Web.HttpContext.Current.Request.PhysicalPath;
                    this._WebPageName = System.IO.Path.GetFileName(myWebPagePhysicalFilePath);

                    return this._WebPageName;
                }
                catch (Exception ex)
                {
                    RealTimeTrace(ex);
                    return this._WebPageName;
                }
            }
        }

        private string _ApplicationFolder = System.String.Empty;
        /// <summary>
        /// Gets the absolute path to the folder where the running Assembly is stored.
        /// </summary>
        private string ApplicationFolder
        {
            get
            {
                try
                {
                    // Check if we have already setup the internal variable
                    if (this._ApplicationFolder.Length > 0)
                    {
                        return this._ApplicationFolder;
                    }

                    // Check for an ASP.NET Web application
                    if (this.IsWebApplication)
                    {
                        this._ApplicationFolder = this.WebApplicationFolder;
                        return this._ApplicationFolder;
                    }

                    // By default get the folder in which the running exe process is stored.
                    this._ApplicationFolder = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

                    //Check for execution in design mode within Visual Studio
                    if (this._ApplicationFolder.Contains("Application Data"))
                    {
                        if (this._ApplicationFolder.Contains("Microsoft"))           
                        {
                    		 // for security reason, check that this folder is within the local Application Data folder.
                            string myLocalApplicationData = System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
                            if (this._ApplicationFolder.StartsWith(myLocalApplicationData))
	                        {
                                // Execution is taking place within Visual Studio in design mode.
                                // Store the RealtimeTrace.log file to the "my Documents" root folder.
                                this._ApplicationFolder = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

                            } // if (this._ApplicationFolder.StartsWith(myDocumentsFolderPath))
                        } // if (this._ApplicationFolder.Contains("Microsoft"))
                    } //if (this._ApplicationFolder.Contains("Application Data"))
                    
                    return this._ApplicationFolder;
                }
                catch (Exception ex)
                {
                    RealTimeTrace(ex);
                    return System.String.Empty;
                }
            }
        }

        private string _LogFileName = @"RealTimeTrace.log";
        /// <summary>
        /// Gets the log filename. By default prefix the name by the application exe name.
        /// </summary>
        private string LogFileName
        {
            get
            {
                try
                {
                    string myFilename = this._LogFileName;

                    // Check for unforeseen bad value
                    if (System.String.IsNullOrEmpty(myFilename))
                    {
                        myFilename = @"RealTimeTrace.log";
                    }

                    // Check for an ASP.NET Web application
                    if (this.IsWebApplication)
                    {
                        // This is a security concern :
                        // do not let an attacker to read the log file through direct http request.
                        // To do this : just postfix the name with an extension that is mapped to an HttpForbiddenhandler
                        myFilename = myFilename + ".webinfo";
                    }

                    if ( !this.UseApplicationNameAsPrefix)
                    {
                        return myFilename;
                    }     
      
                    // build the default application name that will serves as a prefix for the log file name.
                    string myApplicationName = this.ExeProcessName;

                    // Check for an ASP.NET Web application
                    if (this.IsWebApplication)
                    {
                        myApplicationName = this.WebPageName;
                    }

                    myFilename = myApplicationName + "." + myFilename;
                 
                    return myFilename;
                }
                catch (Exception ex)
                {
                    RealTimeTrace(ex);
                    return this._LogFileName;
                }
            }
        }

        private string _LogFilePath = System.String.Empty;
        /// <summary>
        /// Gets the absolute path to the log file.
        /// </summary>
        private string LogFilePath
        {
            get
            {
                try
                {
                    // Check if we have already setup the internal variable
                    if (this._LogFilePath.Length > 0)
                    {
                        return this._LogFilePath;
                    }

                    this._LogFilePath = this.ApplicationFolder +
                                System.IO.Path.DirectorySeparatorChar +
                                this.LogFileName;

                    return this._LogFilePath;
                }
                catch (Exception ex)
                {
                    RealTimeTrace(ex);
                    return System.String.Empty;
                }
            }
        }

        private long _MaxSizeInKbytes = 4096;
        /// <summary>
        /// Gets or Sets the maximum Log file size in Kilo bytes.
        /// </summary>
        private long MaxSizeInKbytes
        {
            get
            {
                return this._MaxSizeInKbytes;
            }
            set
            {
                if (value > 0)
                {
                    this._MaxSizeInKbytes = value;
                }
            }
        }

        private bool Insert(string value)
        {
            try
            {
                // Check for input value
                if (System.String.IsNullOrEmpty(value))
                {
                    return true;
                }

                if (!this.BackupAndClearLogfile())
                {
                    // TODO : think of it for the next release
                }

                // try to get a stream writer 
                System.IO.StreamWriter myWriter;
                try
                {
                    myWriter = new System.IO.StreamWriter(this.LogFilePath, true);
                }
                catch (Exception ex)
                {
                    string myMsg = System.String.Format("Cannot Write to file : '{0}'", this.LogFilePath);  
                    throw new RealTimeTraceException(myMsg,ex);
                }

                try
                {
                    myWriter.WriteLine(value);
                }
                catch (Exception ex)
                {

                    throw ex;
                }
                finally
                {
                    if (!(myWriter==null))
                    {
                        myWriter.Flush();
                        myWriter.Close();
                        myWriter.Dispose();
                        myWriter = null;
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                RealTimeTrace(ex, value);
                return false;
            }

        }

        /// <summary>
        /// Checks if the log file size is greater than the MaxSizeInKbytes. 
        /// If the file is greater than expected it is copied to a file with the same name but with a .0 suffix; 
        /// then the original log file is deleted.
        /// </summary>
        /// <returns>Returns true if execution succeeded, false otherwise.</returns>
        private bool BackupAndClearLogfile()
        {
            try
            {
                if (!System.IO.File.Exists(this.LogFilePath))
                {
                    return true;
                }

                System.IO.FileInfo myFileInfo = new System.IO.FileInfo(this.LogFilePath);
                if (myFileInfo == null)
                {
                    return false;
                }

                // Get the size of the log file
                long myFileSizeInBytes = myFileInfo.Length;
                long myFileSizeInKBytes = 0;
                if (myFileSizeInBytes > 1024L)
                {
                    myFileSizeInKBytes = myFileSizeInBytes / 1024L;
                }

                if (myFileSizeInKBytes <= this.MaxSizeInKbytes)
                {
                    return true;
                }

                // now we are sure the log file is too big
                string myBackupFilePath = this.LogFilePath + ".0";

                // Check for an ASP.NET Web application
                if (this.IsWebApplication)
                {
                    // This is a security concern :
                    // do not let an attacker to read the log file through direct http request.
                    // To do this : just postfix the name with an extension that is mapped to an HttpForbiddenhandler
                    myBackupFilePath = myBackupFilePath + ".webinfo";
                }

                // copy the current log file to the backup file
                // any existing backup file is overwritten
                myFileInfo.CopyTo(myBackupFilePath,true);

                // Wait 3 seconds to let the OS finish the copy operation
                System.Threading.Thread.Sleep(3000);

                // Try to delete the current log file
                myFileInfo.Delete();

                // Wait three seconds to let the OS finish the delete operation
                System.Threading.Thread.Sleep(1000);

                return true;
            }
            catch (Exception ex)
            {
                RealTimeTrace(ex);
                return false;
            }
        }

        #endregion

        #region Constructors

        public TraceLogFileProvider()
        {

        }
        #endregion


    }
}
